/****************************************************
 * Description: Controller for 服务器信息
 * Copyright:   Copyright (c) 2019
 * Company:     ry
 * @author reywong
 * @version 1.0
 * @see
HISTORY
 *  2019-12-04 reywong Create File
 **************************************************/
package cn.com.ry.framework.application.meteor.meteor.machineinfo.web;

import ch.ethz.ssh2.Connection;
import ch.ethz.ssh2.Session;
import cn.com.ry.framework.application.meteor.framework.exception.ValidationException;
import cn.com.ry.framework.application.meteor.framework.json.XjjJson;
import cn.com.ry.framework.application.meteor.framework.security.annotations.*;
import cn.com.ry.framework.application.meteor.framework.spring.SpringTool;
import cn.com.ry.framework.application.meteor.framework.ssh.SshTool;
import cn.com.ry.framework.application.meteor.framework.utils.Excel2007Util;
import cn.com.ry.framework.application.meteor.framework.utils.SnowflakeIdWorker;
import cn.com.ry.framework.application.meteor.framework.web.SpringControllerSupport;
import cn.com.ry.framework.application.meteor.framework.web.support.Pagination;
import cn.com.ry.framework.application.meteor.framework.web.support.QueryParameter;
import cn.com.ry.framework.application.meteor.framework.web.support.XJJParameter;
import cn.com.ry.framework.application.meteor.meteor.machineinfo.entity.MachineinfoEntity;
import cn.com.ry.framework.application.meteor.meteor.machineinfo.service.MachineinfoService;
import cn.com.ry.framework.application.meteor.meteor.rsa.entity.RsaEntity;
import cn.com.ry.framework.application.meteor.meteor.rsa.service.RsaService;
import cn.com.ry.framework.application.meteor.meteor.websocket.service.WebsocketService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

@Controller
@RequestMapping("/meteor/machineinfo")
public class MachineinfoController extends SpringControllerSupport {
    @Autowired
    private MachineinfoService machineinfoService;
    @Autowired
    private RsaService rsaService;
    @Autowired
    private WebsocketService websocketService;




    @SecPrivilege(title = "服务器管理")
    @SecList
    @RequestMapping(value = "/index")
    public String index(Model model) {
        String page = this.getViewPath("index");
        return page;
    }

    @SecList
    @RequestMapping(value = "/list")
    public String list(Model model,
                       @QueryParameter XJJParameter query,
                       @ModelAttribute("page") Pagination page
    ) {
        page = machineinfoService.findPage(query, page);
        return getViewPath("list");
    }

    @SecCreate
    @RequestMapping("/input")
    public String create(@ModelAttribute("machineinfo") MachineinfoEntity machineinfo, Model model) {
        String hostName = "";
        try {
            InetAddress address = InetAddress.getLocalHost();
            hostName = address.getHostAddress();
            //默认通过代理的方式
            //获取agentId
            SnowflakeIdWorker idWorker = new SnowflakeIdWorker();
            Long longAgentId = idWorker.nextId();

            //获取rsa列表
            List<RsaEntity> rsaEntityList = rsaService.findAll();
            model.addAttribute("hostName", hostName);

            model.addAttribute("arthasAgentId", longAgentId);
            model.addAttribute("rsaList", rsaEntityList);
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
        return getViewPath("input");
    }

    @SecEdit
    @RequestMapping("/input/{id}")
    public String edit(@PathVariable("id") Long id, Model model) {
        MachineinfoEntity machineinfo = machineinfoService.getById(id);
        Integer arthasPort = machineinfo.getArthasPort();
        if (arthasPort == 7777) {
            machineinfo.setConnectType("dl");
        } else {
            machineinfo.setConnectType("zl");
        }
        model.addAttribute("machineinfo", machineinfo);
        //获取rsa列表
        List<RsaEntity> rsaEntityList = rsaService.findAll();
        model.addAttribute("rsaList", rsaEntityList);
        return getViewPath("input");
    }

    @SecCreate
    @SecEdit
    @RequestMapping("/save")
    @ResponseBody
    public XjjJson save(@ModelAttribute MachineinfoEntity machineinfo) {
        machineinfo.setCreateTime(new Date());
        machineinfo.setServerStatus("0");
        validateSave(machineinfo);
        Integer arthasPort = machineinfo.getArthasPort();
        if (arthasPort != 7777) {
            machineinfo.setArthasAgentId("");
        }
        if (machineinfo.isNew()) {
            machineinfoService.save(machineinfo);
        } else {
            machineinfoService.update(machineinfo);
        }
        return XjjJson.success("保存成功");
    }


    /**
     * 数据校验
     **/
    private void validateSave(MachineinfoEntity machineinfo) {
        //必填项校验
        // 判断机器名称是否为空
        if (null == machineinfo.getHostname()) {
            throw new ValidationException("校验失败，机器名称不能为空！");
        }
        if (null == machineinfo.getLoginType()) {
            throw new ValidationException("校验失败，登录类型不能为空！");
        } else {
            if (machineinfo.getLoginType().equals("rsa")) {
                // 判断登陆账号是否为空
                if (null == machineinfo.getRsaId()) {
                    throw new ValidationException("校验失败，私钥不能为空！");
                }
            } else {
                // 判断登陆账号是否为空
                if (null == machineinfo.getUsername()) {
                    throw new ValidationException("校验失败，登陆账号不能为空！");
                }
                // 判断密码是否为空
                if (null == machineinfo.getPassword()) {
                    throw new ValidationException("校验失败，密码不能为空！");
                }
            }
        }
        // 判断agent端口是否为空
        if (null == machineinfo.getModuleName()) {
            throw new ValidationException("校验失败，项目模块不能为空！");
        }
        // 判断agent端口是否为空
        if (null == machineinfo.getArthasPort()) {
            throw new ValidationException("校验失败，agent端口不能为空！");
        } else {
            // 判断agent端口是否为空
            if (machineinfo.getArthasPort() == 7777 && null == machineinfo.getArthasAgentId()) {
                throw new ValidationException("校验失败，agentId不能为空！");
            }
        }

        // 判断服务器连接状态是否为空
        if (null == machineinfo.getServerStatus()) {
            throw new ValidationException("校验失败，服务器连接状态不能为空！");
        }
        // 判断状态是否为空
        if (null == machineinfo.getStatus()) {
            throw new ValidationException("校验失败，状态不能为空！");
        }
        // 判断创建时间是否为空
        if (null == machineinfo.getCreateTime()) {
            throw new ValidationException("校验失败，创建时间不能为空！");
        }
        // 判断创建人员ID是否为空
        if (null == machineinfo.getCreatePersonId()) {
            throw new ValidationException("校验失败，创建人员ID不能为空！");
        }
        // 判断操作人员名称是否为空
        if (null == machineinfo.getCreatePersonName()) {
            throw new ValidationException("校验失败，操作人员名称不能为空！");
        }
    }

    @SecDelete
    @RequestMapping("/delete/{id}")
    @ResponseBody
    public XjjJson delete(@PathVariable("id") Long id) {
        machineinfoService.delete(id);
        return XjjJson.success("成功删除1条");
    }

    @SecDelete
    @RequestMapping("/delete")
    @ResponseBody
    public XjjJson delete(@RequestParam("ids") Long[] ids) {
        if (ids == null || ids.length == 0) {
            return XjjJson.error("没有选择删除记录");
        }
        for (Long id : ids) {
            machineinfoService.delete(id);
        }
        return XjjJson.success("成功删除" + ids.length + "条");
    }

    /**
     * 导入用户
     *
     * @param model
     * @return
     */
    @RequestMapping(value = "/import")
    public String importExcel(Model model) {
        return getViewPath("import");
    }

    /**
     * 导入
     *
     * @param model
     * @return
     */
    @SecCreate
    @SecEdit
    @RequestMapping(value = "/import/save")
    @ResponseBody
    public XjjJson saveImport(Model model, @RequestParam(value = "fileId", required = false) Long fileId) {
        System.out.println("上传开始----");
        try {
            Map<String, Object> map = machineinfoService.saveImport(fileId);
            int allCnt = (Integer) map.get("allCnt");
            return XjjJson.success("导入成功：本次共计导入数据" + allCnt + "条");
        } catch (ValidationException e) {
            return XjjJson.error("导入失败：<br/>" + e.getMessage());
        }
    }

    /**
     * 导出用户信息
     *
     * @param request
     * @param response
     * @return
     */
    @SecList
    @RequestMapping(value = "/export/excel")
    public String exportExcel(HttpServletRequest request, HttpServletResponse response) {
        List<MachineinfoEntity> userList = machineinfoService.findAll();
        LinkedHashMap<String, String> columns = new LinkedHashMap<String, String>();
        columns.put("id", "id");
        columns.put("hostname", "机器名称");
        columns.put("username", "登陆账号");
        columns.put("password", "密码");
        columns.put("port", "远程连接端口号");
        columns.put("arthasIp", "agentIP");
        columns.put("arthasPort", "agent端口");
        columns.put("arthasAgentId", "agentId");
        columns.put("serverStatus", "服务器连接状态");
        columns.put("moduleName", "模块名称");
        columns.put("status", "状态");
        columns.put("createTime", "创建时间");
        columns.put("createPersonId", "创建人员ID");
        columns.put("createPersonName", "操作人员名称");
        Excel2007Util.write(userList, columns, response, "machineinfo-export");
        return null;
    }

    @SecEdit
    @RequestMapping("/status/{id}")
    public String status(@PathVariable("id") Long id, Model model) {
        MachineinfoEntity machineinfo = machineinfoService.getById(id);
        model.addAttribute("machineinfo", machineinfo);
        return getViewPath("status");
    }


    @SecCreate
    @SecEdit
    @RequestMapping("/saveStatus")
    @ResponseBody
    public XjjJson saveStatus(@ModelAttribute MachineinfoEntity machineinfo) {
        //必填项校验
        // 判断状态是否为空
        if (null == machineinfo.getStatus()) {
            throw new ValidationException("校验失败，状态不能为空！");
        }
        // 判断创建时间是否为空
        if (null == machineinfo.getCreateTime()) {
            throw new ValidationException("校验失败，创建时间不能为空！");
        }
        // 判断创建人员ID是否为空
        if (null == machineinfo.getCreatePersonId()) {
            throw new ValidationException("校验失败，创建人员ID不能为空！");
        }
        // 判断操作人员名称是否为空
        if (null == machineinfo.getCreatePersonName()) {
            throw new ValidationException("校验失败，操作人员名称不能为空！");
        }
        if (machineinfo.isNew()) {
            return XjjJson.error("参数错误");
        } else {
            machineinfoService.update(machineinfo);
        }
        return XjjJson.success("保存成功");
    }

    @SecCreate
    @SecEdit
    @RequestMapping("/modifyServerStatus/{machineId}/{serverStatus}")
    @ResponseBody
    public XjjJson modifyServerStatus(@PathVariable("machineId") Long machineId, @PathVariable("serverStatus") String serverStatus) {
        // 判断创建时间是否为空
        if (null != machineId) {
            MachineinfoEntity machineinfoEntity = new MachineinfoEntity();
            machineinfoEntity.setId(machineId);
            machineinfoEntity.setServerStatus(serverStatus);
            machineinfoService.update(machineinfoEntity);
        }
        return XjjJson.success("保存成功");
    }

    @SecEdit
    @RequestMapping(value = "/agent/{machineId}")
    public String agent(@PathVariable("machineId") Long machineId, Model model) {
        String page = this.getViewPath("agent");
        if (null != machineId) {
            MachineinfoEntity machineinfoEntity = machineinfoService.getById(machineId);
            model.addAttribute("machine", machineinfoEntity);
        }
        return page;
    }


    @SecEdit
    @RequestMapping(value = "/initMachine/{machineId}")
    @ResponseBody
    public XjjJson initMachine(@PathVariable("machineId") Long machineId) {
        //1. 检查账号密码
        //2. 上传arthas
        //3. 初始化arthas
        //4. 选择需要操作的应用
        if (null != machineId) {
            Connection connection = null;
            Session session = null;
            try {
                connection = websocketService.getConnection(machineId);
                //上传arthas
                session = connection.openSession();
                boolean hasArthas = SshTool.checkFile(session, "meteor");
                boolean flag = false;
                if (!hasArthas) {
                    //获取arthas资源
                    byte[] data = SpringTool.getResourceBytes("agent/meteor.tar.gz");
                    if (null != data && data.length > 0) {
                        String filePath = "/tmp/meteor.tar.gz";
                        flag = SshTool.uploadAndUnTar(connection, data, filePath, "meteor");
                    }


                } else {
                    flag = true;
                }
                MachineinfoEntity tmpMachineinfoEntity = new MachineinfoEntity();
                tmpMachineinfoEntity.setId(machineId);
                //0初始状态  1 agent上传成功  3 agent上传失败
                if (flag) {
                    tmpMachineinfoEntity.setServerStatus("1");
                    machineinfoService.update(tmpMachineinfoEntity);
                    return XjjJson.success("meteor-agent上传成功");
                } else {
                    tmpMachineinfoEntity.setServerStatus("3");
                    machineinfoService.update(tmpMachineinfoEntity);
                    return XjjJson.error("meteor-agent上传失败");
                }
            } catch (Exception e) {
                throw new ValidationException(e.getMessage(), e.getCause());
            } finally {
                if (null != connection) {
                    connection.close();
                }
                if (null != session) {
                    session.close();
                }
            }
        } else {
            return XjjJson.error("参数【machineId】为空");
        }

    }
}

